package com.bj58.ecdata.dao.statementcreater;

import com.bj58.ecdata.dao.annotation.ProcedureName;
import com.bj58.ecdata.dao.util.Common;
import com.bj58.ecdata.dao.util.OutSQL;

import java.lang.reflect.Field;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.List;

public class BJ58ProcCSCreater
  extends PSCreaterBase
{
  public <I> CallableStatement createDelete(Class<?> clazz, Connection connection, I id, OutSQL sql)
    throws Exception
  {
    List<Field> fieldList = Common.getIdFields(clazz);
    if (fieldList.size() != 1) {
      throw new Exception("无法根据主键删除：主键不存在 或 有两个以上的主键");
    }
    ProcedureName des = Common.getProc(clazz);
    if (des != null)
    {
      StringBuffer sbSql = new StringBuffer("{call ");
      sbSql.append(des.delete());
      sbSql.append("(?,?,?)");
      sbSql.append("}");
      
      sql.setSql(sbSql.toString());
      String columnName = Common.getDBCloumnName(clazz, (Field)fieldList.get(0));
      CallableStatement cstmt = connection.prepareCall(sql.getSql());
      cstmt.registerOutParameter("ReturnValue", 4);
      cstmt.registerOutParameter("RowCount", 4);
      cstmt.setString("Where", columnName + "=" + id.toString());
      
      return cstmt;
    }
    throw new Exception("实体没有定义:@ProcedureName");
  }
  
  public CallableStatement createDeleteByCustom(Class<?> clazz, Connection connection, String condition, OutSQL sql)
    throws Exception
  {
    ProcedureName des = Common.getProc(clazz);
    if (des != null)
    {
      StringBuffer sbSql = new StringBuffer("{call ");
      sbSql.append(des.delete());
      sbSql.append("(?,?,?)");
      sbSql.append("}");
      sql.setSql(sbSql.toString());
      
      CallableStatement cstmt = connection.prepareCall(sql.getSql());
      cstmt.registerOutParameter("ReturnValue", 4);
      cstmt.registerOutParameter("RowCount", 4);
      cstmt.setString("Where", condition);
      
      return cstmt;
    }
    throw new Exception("实体没有定义:@ProcedureName");
  }
  
  public CallableStatement createGetByCustom(Class<?> clazz,String tableSuffix, Connection connection, String columns, String condition, String orderBy, OutSQL sql)
    throws Exception
  {
    ProcedureName des = Common.getProc(clazz);
    if (des != null)
    {
      StringBuffer sbSql = new StringBuffer("{call ");
      sbSql.append(des.load());
      sbSql.append("(?,?,?,?,?)");
      sbSql.append("}");
      
      sql.setSql(sbSql.toString());
      CallableStatement cstmt = connection.prepareCall(sql.getSql());
      
      cstmt.registerOutParameter("ReturnValue", 4);
      cstmt.registerOutParameter("RowCount", 4);
      cstmt.setString("OrderByFields", orderBy);
      cstmt.setString("SelectColumns", columns);
      cstmt.setString("Where", condition);
      
      return cstmt;
    }
    throw new Exception("实体没有定义:@ProcedureName");
  }
  
  public CallableStatement createGetByPage(Class<?> clazz,String tableSuffix, Connection connection, String condition, String columns, int page, int pageSize, String orderBy, OutSQL sql)
    throws Exception
  {
    ProcedureName des = Common.getProc(clazz);
    if (des != null)
    {
      StringBuffer sbSql = new StringBuffer("{call ");
      sbSql.append(des.locaByPage());
      sbSql.append("(?,?,?,?,?,?,?)");
      sbSql.append("}");
      
      sql.setSql(sbSql.toString());
      CallableStatement cstmt = connection.prepareCall(sql.getSql());
      
      cstmt.registerOutParameter("ReturnValue", 4);
      cstmt.registerOutParameter("RowCount", 4);
      
      cstmt.setInt("PageSize", pageSize);
      cstmt.setInt("CurrentPage", page);
      cstmt.setString("SelectColumns", columns);
      cstmt.setString("OrderByFields", orderBy);
      cstmt.setString("Where", condition);
      
      return cstmt;
    }
    throw new Exception("实体没有定义:@ProcedureName");
  }
  
  public <I> CallableStatement createGetEntity(Class<?> clazz, Connection connection, I id, OutSQL sql)
    throws Exception
  {
    List<Field> fieldList = Common.getIdFields(clazz);
    if (fieldList.size() != 1) {
      throw new Exception("无法根据主键ID获取数据：主键不存在 或 有两个以上的主键");
    }
    ProcedureName des = Common.getProc(clazz);
    if (des != null)
    {
      StringBuffer sbSql = new StringBuffer("{call ");
      sbSql.append(des.load());
      sbSql.append("(?,?,?,?,?)");
      sbSql.append("}");
      
      sql.setSql(sbSql.toString());
      String columnName = Common.getDBCloumnName(clazz, (Field)fieldList.get(0));
      
      CallableStatement cstmt = connection.prepareCall(sql.getSql());
      cstmt.registerOutParameter("ReturnValue", 4);
      cstmt.registerOutParameter("RowCount", 4);
      cstmt.setString("OrderByFields", "");
      cstmt.setString("SelectColumns", "*");
      cstmt.setString("Where", columnName + "=" + id.toString());
      
      return cstmt;
    }
    throw new Exception("实体没有定义:@ProcedureName");
  }
  
  public CallableStatement createUpdateByCustom(Class<?> clazz, Connection connection, String updateStatement, String condition, OutSQL sql)
    throws Exception
  {
    ProcedureName des = Common.getProc(clazz);
    if (des != null)
    {
      StringBuffer sbSql = new StringBuffer("{call ");
      sbSql.append(des.update());
      sbSql.append("(?,?,?,?)");
      sbSql.append("}");
      
      sql.setSql(sbSql.toString());
      CallableStatement cstmt = connection.prepareCall(sql.getSql());
      
      cstmt.registerOutParameter("ReturnValue", 4);
      cstmt.registerOutParameter("RowCount", 4);
      cstmt.setString("UpdateStatement", updateStatement);
      cstmt.setString("Where", condition);
      
      return cstmt;
    }
    throw new Exception("实体没有定义:@ProcedureName");
  }
  
  public CallableStatement createUpdateEntity(Object bean, Connection connection, OutSQL sql)
    throws Exception
  {
    List<Field> fieldList = Common.getAllFields(bean.getClass());
    if (fieldList.size() > 0)
    {
      ProcedureName des = Common.getProc(bean.getClass());
      if (des != null)
      {
        StringBuffer sbSql = new StringBuffer("{call ");
        sbSql.append(des.updateByID());
        sbSql.append("(?,?");
        for (int i = 0; i < fieldList.size(); i++) {
          sbSql.append(",?");
        }
        sbSql.append(")");
        sbSql.append("}");
        
        sql.setSql(sbSql.toString());
        CallableStatement cstmt = connection.prepareCall(sql.getSql());
        cstmt.registerOutParameter("ReturnValue", 4);
        cstmt.registerOutParameter("RowCount", 4);
        for (Field f : fieldList) {
          Common.setPara(cstmt, bean, f);
        }
        return cstmt;
      }
      throw new Exception("实体没有定义:@ProcedureName");
    }
    throw new Exception("表实体没有字段");
  }
  
  public CallableStatement createInsert(Object bean, Connection connection, OutSQL sql)
    throws Exception
  {
    Class<?> clazz = bean.getClass();
    List<Field> fieldList = Common.getInsertableFields(clazz);
    List<Field> idFields = Common.getIdentityFields(clazz);
    if ((fieldList.size() > 0) && ((idFields == null) || (idFields.size() <= 1)))
    {
      ProcedureName des = Common.getProc(clazz);
      if (des != null)
      {
        StringBuffer sbSql = new StringBuffer("{call ");
        sbSql.append(des.insert());
        sbSql.append("(?,?");
        if ((idFields != null) && (idFields.size() == 1)) {
          sbSql.append(",?");
        }
        for (int i = 0; i < fieldList.size(); i++) {
          sbSql.append(",?");
        }
        sbSql.append(")");
        sbSql.append("}");
        
        sql.setSql(sbSql.toString());
        CallableStatement cstmt = connection.prepareCall(sql.getSql());
        cstmt.registerOutParameter("ReturnValue", 4);
        cstmt.registerOutParameter("RowCount", 4);
        Class<?> idColumnType;
        if ((idFields != null) && (idFields.size() == 1))
        {
          String idColumn = Common.getDBCloumnName(bean.getClass(), (Field)idFields.get(0));
          idColumnType = ((Field)idFields.get(0)).getType();
          if ((idColumnType.equals(Long.TYPE)) || (idColumnType.equals(Long.class))) {
            cstmt.registerOutParameter(idColumn, -5);
          } else if ((idColumnType.equals(Integer.TYPE)) || (idColumnType.equals(Integer.class))) {
            cstmt.registerOutParameter(idColumn, 4);
          } else if (idColumnType.equals(String.class)) {
            cstmt.registerOutParameter(idColumn, 12);
          } else if ((idColumnType.equals(Short.class)) || (idColumnType.equals(Short.TYPE))) {
            cstmt.registerOutParameter(idColumn, 5);
          } else if ((idColumnType.equals(Byte.class)) || (idColumnType.equals(Byte.TYPE))) {
            cstmt.registerOutParameter(idColumn, -7);
          } else {
            throw new Exception("未知的主键类型： WWW58COM.Common.DAO.SqlCreate.ProcParaCreate");
          }
        }
        for (Field f : fieldList) {
          Common.setPara(cstmt, bean, f);
        }
        return cstmt;
      }
      throw new Exception("实体没有定义:@ProcedureName");
    }
    throw new Exception("表实体没有字段，或有两个以上的ID字段");
  }
  
  public PreparedStatement createGetCount(Class<?> clazz,String tableSuffix, Connection conn, String condition, OutSQL sql)
    throws Exception
  {
    throw new Exception("not implement getCount in procDAO");
  }
  
  public <I> PreparedStatement createDeleteByIDS(Class<?> clazz, Connection conn, I[] ids, OutSQL sql)
    throws Exception
  {
    throw new UnsupportedOperationException("Not supported for proc");
  }
  
  public <I> PreparedStatement createUpdateByID(Class<?> clazz, Connection conn, String updateStatement, I id, OutSQL sql)
    throws Exception
  {
    throw new UnsupportedOperationException("Not supported for proc");
  }
}
